#!/bin/bash

# 单个微前端应用部署脚本
# 使用方法: ./deploy-app.sh [app-name] [environment] [version]
# 示例: ./deploy-app.sh login-app production v1.0.0

set -e

# 配置
APP_NAME=${1:-""}
ENVIRONMENT=${2:-production}
VERSION=${3:-latest}
DOCKER_REGISTRY="your-registry.com"
IMAGE_NAME="${DOCKER_REGISTRY}/${APP_NAME}"

# 应用配置
declare -A APP_CONFIG
APP_CONFIG[login-app]="3003"
APP_CONFIG[system-app]="3005"
APP_CONFIG[dashboard-app]="3007"
APP_CONFIG[tenant-app]="3009"
APP_CONFIG[tool-app]="3006"
APP_CONFIG[workflow-app]="3008"
APP_CONFIG[monitor-app]="3010"

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

log_debug() {
    echo -e "${BLUE}[DEBUG]${NC} $1"
}

# 显示帮助信息
show_help() {
    echo "单个微前端应用部署脚本"
    echo ""
    echo "使用方法:"
    echo "  $0 [app-name] [environment] [version]"
    echo ""
    echo "参数:"
    echo "  app-name     应用名称 (必需)"
    echo "  environment  环境 (默认: production)"
    echo "  version      版本 (默认: latest)"
    echo ""
    echo "支持的应用:"
    for app in "${!APP_CONFIG[@]}"; do
        echo "  - $app (端口: ${APP_CONFIG[$app]})"
    done
    echo ""
    echo "示例:"
    echo "  $0 login-app production v1.0.0"
    echo "  $0 system-app staging"
    echo "  $0 dashboard-app"
}

# 验证应用名称
validate_app_name() {
    if [[ -z "$APP_NAME" ]]; then
        log_error "应用名称不能为空"
        show_help
        exit 1
    fi
    
    if [[ ! ${APP_CONFIG[$APP_NAME]+_} ]]; then
        log_error "不支持的应用: $APP_NAME"
        log_info "支持的应用: ${!APP_CONFIG[*]}"
        exit 1
    fi
    
    log_info "应用: $APP_NAME (端口: ${APP_CONFIG[$APP_NAME]})"
}

# 检查依赖
check_dependencies() {
    log_info "检查部署依赖..."
    
    if ! command -v docker &> /dev/null; then
        log_error "Docker 未安装"
        exit 1
    fi
    
    if ! command -v docker-compose &> /dev/null; then
        log_error "Docker Compose 未安装"
        exit 1
    fi
    
    log_info "依赖检查通过"
}

# 构建单个应用
build_app() {
    log_info "开始构建应用: $APP_NAME..."
    
    # 检查应用目录是否存在
    if [[ ! -d "micro-apps/$APP_NAME" ]]; then
        log_error "应用目录不存在: micro-apps/$APP_NAME"
        exit 1
    fi
    
    # 安装依赖
    log_info "安装依赖..."
    pnpm install --frozen-lockfile
    
    # 构建核心包
    log_info "构建核心包..."
    cd tuxing-packages && pnpm -r build && cd ..
    
    # 构建指定应用
    log_info "构建应用: $APP_NAME..."
    cd "micro-apps/$APP_NAME" && pnpm build && cd ../..
    
    log_info "应用构建完成"
}

# 构建 Docker 镜像
build_docker() {
    log_info "构建 Docker 镜像: $IMAGE_NAME:$VERSION..."
    
    docker build \
        -f Dockerfile.single \
        -t "$IMAGE_NAME:$VERSION" \
        -t "$IMAGE_NAME:latest" \
        --build-arg APP_NAME="$APP_NAME" \
        .
    
    log_info "Docker 镜像构建完成"
}

# 推送镜像
push_image() {
    log_info "推送镜像到仓库..."
    
    docker push "$IMAGE_NAME:$VERSION"
    docker push "$IMAGE_NAME:latest"
    
    log_info "镜像推送完成"
}

# 本地测试
test_local() {
    log_info "本地测试应用..."
    
    # 停止可能存在的容器
    docker stop "$APP_NAME" 2>/dev/null || true
    docker rm "$APP_NAME" 2>/dev/null || true
    
    # 运行容器
    docker run -d \
        --name "$APP_NAME" \
        -p "${APP_CONFIG[$APP_NAME]}:80" \
        "$IMAGE_NAME:$VERSION"
    
    # 等待启动
    sleep 10
    
    # 健康检查
    if curl -f "http://localhost:${APP_CONFIG[$APP_NAME]}/health"; then
        log_info "本地测试通过！"
        log_info "访问地址: http://localhost:${APP_CONFIG[$APP_NAME]}"
    else
        log_error "本地测试失败"
        docker logs "$APP_NAME"
        exit 1
    fi
}

# 部署到服务器
deploy_to_server() {
    log_info "部署到服务器..."
    
    # 创建 docker-compose 文件
    create_compose_file
    
    # 拉取最新镜像
    docker pull "$IMAGE_NAME:$VERSION"
    
    # 停止旧容器
    docker-compose -f "docker-compose.$APP_NAME.yml" down || true
    
    # 启动新容器
    docker-compose -f "docker-compose.$APP_NAME.yml" up -d
    
    # 等待服务启动
    log_info "等待服务启动..."
    sleep 30
    
    # 健康检查
    local port=${APP_CONFIG[$APP_NAME]}
    if curl -f "http://localhost:$port/health"; then
        log_info "部署成功！"
        log_info "访问地址: http://localhost:$port"
    else
        log_error "健康检查失败"
        docker-compose -f "docker-compose.$APP_NAME.yml" logs
        exit 1
    fi
}

# 创建单个应用的 docker-compose 文件
create_compose_file() {
    local port=${APP_CONFIG[$APP_NAME]}
    
    cat > "docker-compose.$APP_NAME.yml" << EOF
version: '3.8'

services:
  $APP_NAME:
    image: $IMAGE_NAME:$VERSION
    ports:
      - "$port:80"
    environment:
      - NODE_ENV=$ENVIRONMENT
    volumes:
      - ./logs:/var/log/nginx
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
EOF
    
    log_debug "创建 docker-compose 文件: docker-compose.$APP_NAME.yml"
}

# 清理
cleanup() {
    log_info "清理资源..."
    
    # 清理未使用的镜像
    docker image prune -f
    
    # 清理构建缓存
    docker builder prune -f
    
    log_info "清理完成"
}

# 回滚
rollback() {
    log_warn "开始回滚应用: $APP_NAME..."
    
    # 停止当前容器
    docker-compose -f "docker-compose.$APP_NAME.yml" down
    
    # 拉取上一个版本
    docker pull "$IMAGE_NAME:previous"
    
    # 启动上一个版本
    docker tag "$IMAGE_NAME:previous" "$IMAGE_NAME:latest"
    docker-compose -f "docker-compose.$APP_NAME.yml" up -d
    
    log_info "回滚完成"
}

# 主函数
main() {
    log_info "开始部署单个微前端应用..."
    log_info "应用: $APP_NAME"
    log_info "环境: $ENVIRONMENT"
    log_info "版本: $VERSION"
    
    validate_app_name
    check_dependencies
    
    case "$ENVIRONMENT" in
        "production")
            build_app
            build_docker
            push_image
            deploy_to_server
            cleanup
            ;;
        "staging")
            build_app
            build_docker
            test_local
            deploy_to_server
            ;;
        "local")
            build_app
            build_docker
            test_local
            ;;
        "rollback")
            rollback
            ;;
        *)
            log_error "未知环境: $ENVIRONMENT"
            log_info "支持的环境: production, staging, local, rollback"
            exit 1
            ;;
    esac
    
    log_info "部署完成！"
}

# 执行主函数
main "$@"
